﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.DataSource
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;

namespace Microsoft.InfoCards
{
  internal abstract class DataSource : IDisposable
  {
    private string m_instanceId;
    private bool m_isLoaded;
    private ReaderWriterLock m_lock;
    private bool m_isDisposed;
    private string m_sourceId;
    private bool m_isCleared;

    protected DataSource(string instanceId, string sourceId)
    {
      this.m_instanceId = instanceId;
      this.m_sourceId = sourceId;
      this.m_lock = new ReaderWriterLock();
    }

    public string SourceId
    {
      get
      {
        this.ThrowIfDisposed();
        return this.m_sourceId;
      }
    }

    public bool IsDisposed
    {
      get
      {
        return this.m_isDisposed;
      }
    }

    public bool IsLoaded
    {
      get
      {
        this.ThrowIfDisposed();
        return this.m_isLoaded;
      }
    }

    public bool IsCleared
    {
      get
      {
        return this.m_isCleared;
      }
      set
      {
        this.m_isCleared = value;
      }
    }

    protected internal string InstanceId
    {
      get
      {
        this.ThrowIfDisposed();
        return this.m_instanceId;
      }
      set
      {
        this.ThrowIfDisposed();
        this.m_instanceId = value;
      }
    }

    public bool IsProcessingTransaction()
    {
      this.ThrowIfDisposed();
      this.ThrowIfNotLoaded();
      return this.m_lock.IsWriterLockHeld;
    }

    public void BeginTransaction()
    {
      this.ThrowIfWriteLockHeld();
      this.ThrowIfDisposed();
      this.ThrowIfNotLoaded();
      this.m_lock.AcquireWriterLock(0);
      this.OnBeginTransaction();
    }

    public void CommitTransaction()
    {
      this.ThrowIfDisposed();
      this.ThrowIfNotLoaded();
      this.ThrowIfWriteLockNotHeld();
      this.OnCommitTransaction();
      this.m_lock.ReleaseWriterLock();
    }

    public void RollbackTransaction()
    {
      this.ThrowIfDisposed();
      this.ThrowIfNotLoaded();
      this.ThrowIfWriteLockNotHeld();
      this.OnRollbackTransaction();
      this.m_lock.ReleaseWriterLock();
    }

    public void Load()
    {
      this.ThrowIfDisposed();
      this.OnLoad();
      this.m_isLoaded = true;
    }

    public void Clear()
    {
      this.ThrowIfLoaded();
      this.ThrowIfDisposed();
      this.OnClear();
      this.m_isLoaded = false;
      this.m_isCleared = true;
    }

    public void Close()
    {
      if (!this.m_isLoaded)
        return;
      this.OnClose();
      this.m_isLoaded = false;
    }

    public DataRow GetSingleRow(params QueryParameter[] objectQuery)
    {
      return this.GetSingleRow(QueryDetails.FullRow, objectQuery);
    }

    public DataRow GetSingleRow(QueryDetails details, params QueryParameter[] objectQuery)
    {
      IList<DataRow> dataRowList = this.Query(details, objectQuery);
      if (dataRowList == null || dataRowList.Count == 0)
        return (DataRow) null;
      if (dataRowList.Count > 1)
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreMoreThanOneRowReturnedInSingleMatchQuery")));
      return dataRowList[0];
    }

    public IList<DataRow> Query(params QueryParameter[] objectQuery)
    {
      return this.Query(QueryDetails.FullRow, objectQuery);
    }

    public IList<DataRow> Query(
      QueryDetails details,
      params QueryParameter[] objectQuery)
    {
      this.ThrowIfDisposed();
      this.ThrowIfNotLoaded();
      if (objectQuery == null || objectQuery.Length == 0)
        throw InfoCardTrace.ThrowHelperArgumentNull("query");
      if (!this.IsValidQueryDetails(details))
        throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentException(nameof (details)));
      if (details == QueryDetails.None)
        return (IList<DataRow>) null;
      LocalIdCollection localIdCollection1 = (LocalIdCollection) null;
      bool flag = false;
      try
      {
        try
        {
        }
        finally
        {
          this.m_lock.AcquireReaderLock(0);
          flag = true;
        }
        foreach (QueryParameter match in objectQuery)
        {
          LocalIdCollection localIdCollection2 = new LocalIdCollection();
          if ("localid" == match.IndexName.ToLower(CultureInfo.InvariantCulture))
          {
            for (int index1 = 0; index1 < match.Count; ++index1)
            {
              for (int index2 = 0; index2 < match[index1].ObjectList.Length; ++index2)
              {
                int int32 = Convert.ToInt32(match[index1].ObjectList[index2], (IFormatProvider) NumberFormatInfo.InvariantInfo);
                localIdCollection2.Add(int32);
              }
            }
          }
          else if (!this.SingleMatch(match, localIdCollection2))
          {
            if (localIdCollection1 != null)
            {
              localIdCollection1.Clear();
              break;
            }
            break;
          }
          if (localIdCollection1 == null)
            localIdCollection1 = localIdCollection2;
          else
            localIdCollection1.Filter(localIdCollection2);
        }
      }
      finally
      {
        if (flag)
          this.m_lock.ReleaseReaderLock();
      }
      if (localIdCollection1 == null || localIdCollection1.Count == 0)
        return (IList<DataRow>) null;
      List<DataRow> dataRowList = new List<DataRow>(localIdCollection1.Count);
      foreach (int key in (IEnumerable<int>) localIdCollection1.Keys)
      {
        if (QueryDetails.Identifiers == details)
          dataRowList.Add(new DataRow()
          {
            LocalId = key,
            SourceId = this.SourceId,
            InstanceId = this.InstanceId
          });
        else
          dataRowList.Add(this.ReadRow(key, details));
      }
      return (IList<DataRow>) dataRowList;
    }

    public void Save(DataRow row)
    {
      this.ThrowIfDisposed();
      this.ThrowIfNotLoaded();
      this.ThrowIfWriteLockNotHeld();
      if (row == null)
        throw InfoCardTrace.ThrowHelperArgumentNull(nameof (row));
      if ((!string.IsNullOrEmpty(row.InstanceId) || !string.IsNullOrEmpty(row.SourceId)) && (string.Compare(row.InstanceId, this.InstanceId, StringComparison.Ordinal) != 0 || string.Compare(row.SourceId, this.SourceId, StringComparison.Ordinal) != 0))
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreRowOwnedByOtherDataSource")));
      row.LastChange = DateTime.Now.ToFileTimeUtc();
      this.WriteRow(row);
      row.InstanceId = this.InstanceId;
      row.SourceId = this.SourceId;
    }

    public void Delete(DataRow row)
    {
      this.ThrowIfDisposed();
      this.ThrowIfNotLoaded();
      this.ThrowIfWriteLockNotHeld();
      if (row == null)
        throw InfoCardTrace.ThrowHelperArgumentNull(nameof (row));
      if (row.InstanceId == null || row.SourceId == null)
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreDataSourceRowNotOwned")));
      if (string.Compare(row.InstanceId, this.InstanceId, StringComparison.Ordinal) != 0 || string.Compare(row.SourceId, this.SourceId, StringComparison.Ordinal) != 0)
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreRowOwnedByOtherDataSource")));
      this.RemoveObject(row.LocalId);
    }

    protected internal virtual bool IsValidQueryDetails(QueryDetails details)
    {
      if (QueryDetails.IndexData == (details & QueryDetails.IndexData))
        return QueryDetails.FullRowAndIndexes == (details & QueryDetails.FullRowAndIndexes);
      if (QueryDetails.DataBlob == (details & QueryDetails.DataBlob))
        return QueryDetails.FullRow == (details & QueryDetails.FullRow);
      if (QueryDetails.Header == (details & QueryDetails.Header))
        return QueryDetails.FullHeader == (details & QueryDetails.FullHeader);
      if (QueryDetails.Identifiers == (details & QueryDetails.Identifiers))
        return QueryDetails.Identifiers == (details & QueryDetails.Identifiers);
      return QueryDetails.None == details;
    }

    protected internal virtual void OnBeginTransaction()
    {
      this.ThrowIfDisposed();
    }

    protected internal virtual void OnCommitTransaction()
    {
      this.ThrowIfDisposed();
    }

    protected internal virtual void OnRollbackTransaction()
    {
      this.ThrowIfDisposed();
    }

    protected internal virtual void OnLoad()
    {
      this.ThrowIfDisposed();
    }

    protected internal virtual void OnClose()
    {
      this.ThrowIfDisposed();
    }

    protected internal virtual void OnClear()
    {
      this.ThrowIfDisposed();
    }

    protected internal virtual void OnDispose()
    {
    }

    protected internal abstract void WriteRow(DataRow row);

    protected internal abstract void RemoveObject(int id);

    protected internal abstract DataRow ReadRow(int localId, QueryDetails details);

    protected internal abstract bool SingleMatch(QueryParameter match, LocalIdCollection localIds);

    void IDisposable.Dispose()
    {
      this.OnDispose();
      this.m_isDisposed = true;
    }

    protected internal void ThrowIfWriteLockNotHeld()
    {
      if (!this.m_lock.IsWriterLockHeld)
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreDataSourceWriteLockNotHeld")));
    }

    protected internal void ThrowIfWriteLockHeld()
    {
      if (this.m_lock.IsWriterLockHeld)
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreProcessingTransaction")));
    }

    protected internal void ThrowIfNotLoaded()
    {
      if (!this.m_isLoaded)
        throw InfoCardTrace.ThrowHelperError((Exception) new ObjectDisposedException(nameof (DataSource)));
    }

    protected internal void ThrowIfLoaded()
    {
      if (this.m_isLoaded)
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreIsAlreadyLoaded")));
    }

    protected internal void ThrowIfDisposed()
    {
      if (this.m_isDisposed)
        throw InfoCardTrace.ThrowHelperError((Exception) new ObjectDisposedException(nameof (DataSource)));
    }

    public static QueryParameter CreateDeleteStoreTypeQuery()
    {
      QueryParameter queryParameter = new QueryParameter("ix_objecttype");
      foreach (int num in Enum.GetValues(typeof (StorableObjectType)))
      {
        if (num != 0)
          queryParameter.AddMatch((object) num);
      }
      return queryParameter;
    }
  }
}
